using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

namespace Bzstd.Utility;

/// <summary>
/// 将字符串Trim
/// </summary>
public class TrimmedStringConverter : JsonConverter<string>
{
	public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
	{
		serializer.Converters.Remove(this);
		serializer.Serialize(writer, value?.Trim());
		serializer.Converters.Add(this);
	}

	public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
	{
		serializer.Converters.Remove(this);
		string result = serializer.Deserialize(reader, objectType)?.ToString()!.Trim();
		serializer.Converters.Add(this);
		return result;
	}
}

/// <summary>
/// HttpMethod json转换器
/// </summary>
public class HttpMethodConverter : JsonConverter<HttpMethod>
{
	public override void WriteJson(JsonWriter writer, HttpMethod value, JsonSerializer serializer)
	{
		serializer.Serialize(writer, value?.ToString());
	}

	public override HttpMethod ReadJson(JsonReader reader, Type objectType, HttpMethod existingValue, bool hasExistingValue, JsonSerializer serializer)
	{
		string methodString = serializer.Deserialize<string>(reader);
		return new HttpMethod(methodString?.ToUpper());
	}
}

/// <summary>
/// IPAddress json转换器
/// </summary>
public class IPAddressConverter : JsonConverter<IPAddress>
{
	public override void WriteJson(JsonWriter writer, IPAddress value, JsonSerializer serializer)
	{
		serializer.Serialize(writer, value?.ToString());
	}

	public override IPAddress ReadJson(JsonReader reader, Type objectType, IPAddress existingValue, bool hasExistingValue, JsonSerializer serializer)
	{
		string ipString = serializer.Deserialize<string>(reader);
		return !string.IsNullOrWhiteSpace(ipString) ? IPAddress.Parse(ipString) : null;
	}
}

/// <summary>
/// IPEndPoint json转换器
/// </summary>
public class IPEndPointConverter : JsonConverter<IPEndPoint>
{
	public override void WriteJson(JsonWriter writer, IPEndPoint value, JsonSerializer serializer)
	{
		serializer.Serialize(writer, value != null ? new {value.Address, value.Port} : null);
	}

	public override IPEndPoint ReadJson(JsonReader reader, Type objectType, IPEndPoint existingValue, bool hasExistingValue, JsonSerializer serializer)
	{
		var obj = new { Address = null as IPAddress, Port = 0 };
		obj = (dynamic) serializer.Deserialize(reader, obj.GetType());
		return obj != null ? new IPEndPoint(obj.Address, obj.Port) : null;
	}
}

public class DateTimeConverter : IsoDateTimeConverter
{
	public DateTimeConverter()
	{
		DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
	}

	public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
	{
		if (value is DateTimeOffset dto && dto == DateTimeOffset.MinValue || value is DateTime dt && dt == DateTime.MinValue)
		{
			serializer.Serialize(writer, null);
		}
		else
		{
			base.WriteJson(writer, value, serializer);
		}
	}
}

/// <summary>
/// Boolean json转换器
/// </summary>
public class BooleanConverter : JsonConverter<bool>
{
	public override void WriteJson(JsonWriter writer, bool value, JsonSerializer serializer)
	{
		serializer.Converters.Remove(this);
		serializer.Serialize(writer, value);
		serializer.Converters.Add(this);
	}

	public override bool ReadJson(JsonReader reader, Type objectType, bool existingValue, bool hasExistingValue, JsonSerializer serializer)
	{
		var boolString = serializer.Deserialize<string>(reader);
		if (boolString == null)
		{
			return false;
		}
		else if (bool.TryParse(boolString, out bool boolValue))
		{
			return boolValue;
		}
		else if (long.TryParse(boolString, out long longValue))
		{
			return longValue > 0;
		}
		else
		{
			return false;
		}
	}
}

/// <summary>
/// TimeSpan json转换器
/// </summary>
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
	public override void WriteJson(JsonWriter writer, TimeSpan value, JsonSerializer serializer)
	{
		serializer.Serialize(writer, value.TotalMilliseconds);
	}

	public override TimeSpan ReadJson(JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, JsonSerializer serializer)
	{
		serializer.Converters.Remove(this);
		var timeSpan = serializer.Deserialize<TimeSpan>(reader);
		serializer.Converters.Add(this);
		return timeSpan;
	}
}

public class CaseNamingStrategy : DefaultNamingStrategy
{
	protected override string ResolvePropertyName(string name)
	{
		return new CaseResolver(name).ToCamelCase();
	}
}
